package guggaTests.collections.checkList
{
	import gugga.collections.checkList.CheckList;
	import gugga.collections.checkList.CheckListEvent;
	
	import flexunit.framework.TestCase;
	import flash.utils.Timer;
	import flash.events.Event;

	public class CheckListTest extends TestCase
	{
		public function CheckListTest(methodName:String=null)
		{
			super(methodName);
		}
		
		public function testConstructor() : void
		{
			var checkList:CheckList = new CheckList();
			assertNotNull(
					"checkList should not be null after creation", 
					checkList);
			assertNotUndefined(
					"checkList should not be undefined after creation", 
					checkList);
			
			var myArray : Array = new Array();
			
			var registeredObjects:Array = checkList.RegisteredObjects;
			assertNotNull(
					"registeredObjects Array should not be null after creation", 
					registeredObjects);
			assertNotUndefined(
					"registeredObjects Array should not be undefined after creation", 
					registeredObjects);
			assertEquals(
					"registeredObjects Array should be empty right after creation",
					0, registeredObjects.length);
			
			var checkedObjects:Array = checkList.CheckedObjects;
			assertNotNull(
					"checkedObjects Array should not be null after creation", 
					checkedObjects);
			assertNotUndefined(
					"checkedObjects Array should not be undefined after creation", 
					checkedObjects);
			assertEquals(
					"checkedObjects Array should be empty right after creation",
					0, checkedObjects.length);
			
			var uncheckedObjects:Array = checkList.UncheckedObjects;
			assertNotNull(
					"uncheckedObjects Array should not be null after creation", 
					uncheckedObjects);
			assertNotUndefined(
					"uncheckedObjects Array should not be undefined after creation", 
					uncheckedObjects);
			assertEquals(
					"uncheckedObjects Array should be empty right after creation",
					0, uncheckedObjects.length);
		}
		
		public function testAdd() : void
		{
			var checkList:CheckList = new CheckList();
			
			var object1:Object = new Object();
			checkList.add(object1);
			
			var registeredObjects:Array = checkList.RegisteredObjects;
			assertFalse(
					"registeredObjects Array should not be empty right after adding object1 to the checkList",
					isArrayEmpty(registeredObjects));
			assertTrue(
					"object1 should be registered after adding it to the checkList", 
					checkList.isObjectRegistered(object1));
			assertEquals(
					"registeredObjects Array should contain 1 object after adding object1 to the checkList",
					registeredObjects.length, 
					1);
			assertTrue(
					"registeredObjects Array should contain object1 after adding object1 to the checkList(nothing has been checked yet)",
					arrayContainsItem(registeredObjects, object1));
			
			var uncheckedObjects:Array = checkList.UncheckedObjects;
			assertEquals(
					"uncheckedObjects Array should contain 1 object after adding object1 to the checkList(nothing has been checked yet)",
					uncheckedObjects.length, 
					1);
			assertTrue(
					"uncheckedObjects Array should contain object1 after adding object1 to the checkList(nothing has been checked yet)",
					arrayContainsItem(uncheckedObjects, object1));
			
			var checkedObjects:Array = checkList.CheckedObjects;
			assertTrue(
					"checkedObjects Array should be empty after adding object1 to the checkList(nothing has been checked yet)",
					isArrayEmpty(checkedObjects));
			assertFalse(
					"checkList.isObjectChecked(object1) should be false(nothing has been checked yet)",
					checkList.isObjectChecked(object1));
			
			var object2:Object = new Object();
			checkList.add(object2);
			
			registeredObjects = checkList.RegisteredObjects;
			assertFalse(
					"registeredObjects Array should not be empty right after adding object1 and object2 to the checkList",
					isArrayEmpty(registeredObjects));
			assertTrue(
					"object2 should be registered after adding it to the checkList", 
					checkList.isObjectRegistered(object2));
			assertEquals(
					"registeredObjects Array should contain 2 objects after adding object1 and object2 to the checkList",
					registeredObjects.length, 
					2);
			assertTrue(
					"registeredObjects Array should contain object1 and object2 after adding object1 and object2 to the checkList(nothing has been checked yet)",
					arrayContainsItem(registeredObjects, object1) && arrayContainsItem(registeredObjects, object2));
			
			uncheckedObjects = checkList.UncheckedObjects;
			assertEquals(
					"uncheckedObjects Array should contain 2 objects after adding object1 and object2 to the checkList(nothing has been checked yet)",
					uncheckedObjects.length, 
					2);
			assertTrue(
					"uncheckedObjects Array should contain object1 and object2 after adding object1 and object2 to the checkList(nothing has been checked yet)",
					arrayContainsItem(uncheckedObjects, object1) && arrayContainsItem(uncheckedObjects, object2));
			
			checkedObjects = checkList.CheckedObjects;
			assertTrue(
					"checkedObjects Array should be empty after adding object1 and object2 to the checkList(nothing has been checked yet)",
					isArrayEmpty(checkedObjects));
			assertFalse(
					"checkList.isObjectChecked(object1) && checkList.isObjectChecked(object2) should be false(nothing has been checked yet)",
					checkList.isObjectChecked(object1) && checkList.isObjectChecked(object2));
		}
		
		public function testRemove() : void
		{
			var checkList:CheckList = new CheckList();
			
			var object1:Object = new Object();
			checkList.add(object1);
			
			var object2:Object = new Object();
			checkList.add(object2);
			
			// in order to test checkedObjects Array after remove, I need to 
			// check object2 in the checkList(after checking this object the 
			// checkedObjects Array will contain one object - after removing 
			// this  object, checkedObjects Array should be empty):
			checkList.check(object2);
			
			checkList.remove(object2);
			var registeredObjects:Array = checkList.RegisteredObjects;
			assertFalse(
					"registeredObjects Array should not be empty after removing object2(object1 is still in the checkList)",
					isArrayEmpty(registeredObjects));
			assertEquals(
					"registeredObjects Array should contain 1 object after removing object2 from the checkList(object1 is still in the checkList)",
					registeredObjects.length, 
					1);
			assertTrue(
					"registeredObjects Array should contain object1 after removing object2 from the checkList(object1 is still in the checkList)",
					arrayContainsItem(registeredObjects, object1));
			assertFalse(
					"object2 should not be registered after removing it from the checkList", 
					checkList.isObjectRegistered(object2));
			assertTrue(
					"object1 should be registered after removing object2 from the checkList(object1 is still in the checkList)", 
					checkList.isObjectRegistered(object1));
			
			var checkedObjects:Array = checkList.CheckedObjects;
			assertTrue(
					"checkedObjects Array should be empty after removing object2 from the checkList(nothing else has been checked yet)",
					isArrayEmpty(checkedObjects));
			assertFalse(
					"checkList.isObjectChecked(object2) should be false(object2 has been removed from the checkList)",
					checkList.isObjectChecked(object2));
			
			var uncheckedObjects:Array = checkList.UncheckedObjects;
			assertEquals(
					"uncheckedObjects Array should contain 1 object after adding object1 to the checkList(nothing has been checked yet)",
					uncheckedObjects.length, 
					1);
			assertTrue(
					"uncheckedObjects Array should still contain object1 after removing object2 from the checkList(object1 has not been checked yet)",
					arrayContainsItem(uncheckedObjects, object1));
			
			checkList.remove(object1);
			registeredObjects = checkList.RegisteredObjects;
			assertTrue(
					"registeredObjects Array should now be empty after removing object2 and object1(checkList is empty)",
					isArrayEmpty(registeredObjects));
			assertFalse(
					"object1 should not be registered after removing it from the checkList", 
					checkList.isObjectRegistered(object1));
			
			uncheckedObjects = checkList.UncheckedObjects;
			assertTrue(
					"uncheckedObjects Array should now be empty after removing object2 and object1(checkList is empty)",
					isArrayEmpty(uncheckedObjects));
		}
		
		public function testReset() : void
		{
			var checkList:CheckList = new CheckList();
			
			var object1:Object = new Object();
			checkList.add(object1);
			
			var object2:Object = new Object();
			checkList.add(object2);
			
			checkList.check(object2);
			var checkedObjects:Array = checkList.CheckedObjects;
			assertFalse(
					"checkedObjects Array should not be empty after checking object2",
					isArrayEmpty(checkedObjects));
			assertEquals(
					"checkedObjects Array should contain 1 object after checking object2",
					checkedObjects.length, 
					1);
			assertTrue(
					"checkedObjects Array should contain object2 after checking object2",
					arrayContainsItem(checkedObjects, object2));
			assertTrue(
					"checkList.isObjectChecked(object2) should be true after checking object2", 
					checkList.isObjectChecked(object2));
			
			var uncheckedObjects:Array = checkList.UncheckedObjects;
			assertFalse(
					"uncheckedObjects Array should not be empty after checking object2(object1 is not checked yet)",
					isArrayEmpty(uncheckedObjects));
			assertEquals(
					"uncheckedObjects Array should contain 1 object after checking object2(object1 is not checked yet)",
					uncheckedObjects.length, 
					1);
			assertTrue(
					"uncheckedObjects Array should contain object1(object1 is not checked yet)",
					arrayContainsItem(uncheckedObjects, object1));
			assertFalse(
					"checkList.isObjectChecked(object1) should be false(object1 is not checked yet)", 
					checkList.isObjectChecked(object1));
			
			var registeredObjectsBeforeReset:Array = checkList.RegisteredObjects;
			
			checkList.reset();
			checkedObjects = checkList.CheckedObjects;
			assertTrue(
					"checkedObjects Array should be empty after reset",
					isArrayEmpty(checkedObjects));
			assertFalse(
					"checkList.isObjectChecked(object2) should be false after reset", 
					checkList.isObjectChecked(object2));
			
			uncheckedObjects = checkList.UncheckedObjects;
			assertFalse(
					"uncheckedObjects Array should not be empty after reset(everything is unchecked)",
					isArrayEmpty(uncheckedObjects));
			assertEquals(
					"uncheckedObjects Array should contain 2 object after reset(everything is unchecked)",
					uncheckedObjects.length, 
					2);
			assertTrue(
					"uncheckedObjects Array should contain object1 and object2(everything is unchecked)",
					arrayContainsItem(uncheckedObjects, object1) && arrayContainsItem(uncheckedObjects, object2));
			assertFalse(
					"checkList.isObjectChecked(object1) && checkList.isObjectChecked(object2) should be false(everything is unchecked)", 
					checkList.isObjectChecked(object1) && checkList.isObjectChecked(object2));
			
			var registeredObjectsAfterReset:Array = checkList.RegisteredObjects;
			
			// registered objects should be the same after reset:
			for(var i:Number = 0; i < registeredObjectsBeforeReset.length; i++)
			{
				assertEquals(
					"registeredObjectsBeforeReset[" + i + "] should equals to registeredObjectsAfterReset[" + i + "]",
					registeredObjectsBeforeReset[i],
					registeredObjectsAfterReset[i]);
			}
		}
		
		public function testCheck() : void
		{
			var checkList:CheckList = new CheckList();
			
			var object1:Object = new Object();
			checkList.add(object1);
			
			var object2:Object = new Object();
			checkList.add(object2);
			
			checkList.check(object1);
			var checkedObjects:Array = checkList.CheckedObjects;
			assertFalse(
					"checkedObjects Array should not be empty after checking object1",
					isArrayEmpty(checkedObjects));
			assertEquals(
					"checkedObjects Array should contain 1 object after checking object1",
					checkedObjects.length, 
					1);
			assertTrue(
					"checkedObjects Array should contain object1 after checking object1",
					arrayContainsItem(checkedObjects, object1));
			assertTrue(
					"checkList.isObjectChecked(object1) should be true after checking object1", 
					checkList.isObjectChecked(object1));
			
			var uncheckedObjects:Array = checkList.UncheckedObjects;
			assertFalse(
					"uncheckedObjects Array should not be empty after checking object1(object2 is not checked yet)",
					isArrayEmpty(uncheckedObjects));
			assertEquals(
					"uncheckedObjects Array should contain 1 object after checking object1(object2 is not checked yet)",
					uncheckedObjects.length, 
					1);
			assertTrue(
					"uncheckedObjects Array should contain object2(object2 is not checked yet)",
					arrayContainsItem(uncheckedObjects, object2));
			assertFalse(
					"checkList.isObjectChecked(object2) should be false(object2 is not checked yet)", 
					checkList.isObjectChecked(object2));
			
			checkList.check(object2);
			
			checkedObjects = checkList.CheckedObjects;
			assertFalse(
					"checkedObjects Array should not be empty after checking object2(it also contains object1)",
					isArrayEmpty(checkedObjects));
			assertEquals(
					"checkedObjects Array should contain 2 object after checking object2(it also contains object1)",
					checkedObjects.length, 
					2);
			assertTrue(
					"checkedObjects Array should contain object1 and object2 after checking object2",
					arrayContainsItem(checkedObjects, object1) && arrayContainsItem(checkedObjects, object2));
			assertTrue(
					"checkList.isObjectChecked(object1) && checkList.isObjectChecked(object2) should be true after checking object2(object1 is also checked)", 
					checkList.isObjectChecked(object1) && checkList.isObjectChecked(object2));
			
			uncheckedObjects = checkList.UncheckedObjects;
			assertTrue(
					"uncheckedObjects Array should be empty after checking object2(object1 is also checked)",
					isArrayEmpty(uncheckedObjects));
		}
		
		public function testIsCompleted() : void
		{
			var checkList:CheckList = new CheckList();
			
			assertTrue(
					"checkList.isCompleted() should be true(checkList is empty after creation)",
					checkList.isCompleted());
			
			var object1:Object = new Object();
			checkList.add(object1);
			
			var object2:Object = new Object();
			checkList.add(object2);
			
			assertFalse(
					"checkList.isCompleted() should be false(still has two unchecked objects)",
					checkList.isCompleted());
			
			checkList.check(object2);
			assertFalse(
					"checkList.isCompleted() should be false(still object1 is unchecked, though object2 is checked)",
					checkList.isCompleted());
			
			checkList.check(object1);
			assertTrue(
					"checkList.isCompleted() should be true(all objects were checked)",
					checkList.isCompleted());
		}
		
		public function testCheckListCompletedEvent() : void
		{
			var checkList : CheckList = new CheckList();
			var checkListCompletedHandler : Function = addAsync(checkListSuccedetToDispatchCompletedEvent, 100);
			
			checkList.addEventListener(CheckListEvent.COMPLETED, checkListCompletedHandler);			
			
			var object1 : Object = new Object();
			var object2 : Object = new Object();
			var object3 : Object = new Object();
			
			checkList.add(object1);
			checkList.add(object2);
			checkList.add(object3);
			
			checkList.check(object1);
			checkList.check(object3);
			checkList.check(object2);
			var testis : Object = new Object();
		}
		
		private function checkListSuccedetToDispatchCompletedEvent(aEvent : Event) : void
		{
			var checkList : CheckList = CheckList(aEvent.target);
			assertTrue("CheckList should be completed", checkList.isCompleted());
		}
		
		private function isArrayEmpty(aArray : Array) : Boolean
		{
			if(aArray.length == 0)
			{
				return true;	
			}
			else
			{
				return false;	
			}
		}
		
		private function arrayContainsItem(aArray : Array, aObject : Object) : Boolean
		{
			var objectIndex : int = aArray.indexOf(aObject);
			var containsItem : Boolean;
			if(objectIndex == -1)
			{
				containsItem = false;
			}
			else
			{
				containsItem = true;
			}
			
			return containsItem;
		}
	}
}